package io.scnb.lesson001.demo4;

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 自定义本地线程级别的bean作用域
 * 不同的线程中对应的bean实例是不同的
 * 同一个线程中同名的bean是同一个实例
 */
public class ThreadScope implements Scope {

    public static final String THREAD_SCOPE = "thread";

    private ThreadLocal<Map<String, Object>> beanMap = new ThreadLocal() {
        @Override
        protected Object initialValue() {
            return new HashMap<>();
        }
    };

    /**
     * 返回当前作用域中name对应的bean对象（同一个线程中是同一个bean对象）
     * 如果没有，可以调用objectFactory来创建这个对象
     * @param name 需要检索的bean的名称
     * @param objectFactory
     * @return
     */
    @Override
    public Object get(String name, ObjectFactory<?> objectFactory) {
        Object bean = beanMap.get().get(name);
        if (Objects.isNull(bean)) {
            bean = objectFactory.getObject();
            beanMap.get().put(name, bean);
        }
        return bean;
    }

    /**
     * 将name对应的bean实例从当前作用域中去掉
     * @param name
     * @return
     */
    @Override
    public Object remove(String name) {
        return beanMap.get().remove(name);
    }

    @Override
    public void registerDestructionCallback(String s, Runnable runnable) {
        // bean作用域范围结束的时候调用的方法，用于清理bean对象
        System.out.println(s);
    }

    /**
     * 用于解析相应的上下文数据，比如request作用域将返回request中的属性
     * @param s
     * @return
     */
    @Override
    public Object resolveContextualObject(String s) {
        return null;
    }

    /**
     * 作用域的会话标识，比如session作用域的标识将是sessionid
     * @return
     */
    @Override
    public String getConversationId() {
        return Thread.currentThread().getName();
    }
}
